package easier.fast.app;

import android.content.Context;
import android.graphics.Color;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.scwang.smart.refresh.footer.ClassicsFooter;
import com.scwang.smart.refresh.header.ClassicsHeader;
import com.scwang.smart.refresh.layout.SmartRefreshLayout;
import com.scwang.smart.refresh.layout.api.RefreshFooter;
import com.scwang.smart.refresh.layout.api.RefreshHeader;
import com.scwang.smart.refresh.layout.api.RefreshLayout;
import com.scwang.smart.refresh.layout.listener.DefaultRefreshFooterCreator;
import com.scwang.smart.refresh.layout.listener.DefaultRefreshHeaderCreator;
import easier.fast.AppSettings;
import easier.fast.service.ApiService;
import easier.fast.settings.AppSettingsSerializer;
import easier.fast.settings.RxProtoStoreManager;
import easier.log.logger.AndroidLogAdapter;
import easier.log.logger.Logger;
import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.Single;
import io.reactivex.rxjava3.exceptions.UndeliverableException;
import io.reactivex.rxjava3.functions.Action;
import io.reactivex.rxjava3.functions.Consumer;
import io.reactivex.rxjava3.functions.Function;
import io.reactivex.rxjava3.plugins.RxJavaPlugins;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * app 运行需要的组件
 */
public class ComponentHolder {

    private final Context mContext;

    /**
     * 锁住初始化
     */
    private final Lock mLock = new ReentrantLock();

    /**
     * 标记是否已经初始化成功
     */
    private final AtomicBoolean mInitThirdLib = new AtomicBoolean( false );

    /**
     * app单例
     */
    private final RxProtoStoreManager< AppSettings > mManager;

    /**
     * @param context    context
     * @param isLoggable 是否可以调试
     */
    public ComponentHolder( Context context, boolean isLoggable ) {

        mContext = context.getApplicationContext();

        mManager = new RxProtoStoreManager<>( getContext(), "AppSettings", new AppSettingsSerializer() );

        Logger.clearLogAdapters();
        Logger.addLogAdapter( new AndroidLogAdapter() {
            @Override
            public boolean isLoggable( int priority, @Nullable String tag ) {

                return isLoggable;
            }
        } );

        ApiService.setLoggable( isLoggable );

        RxJavaPlugins.setErrorHandler( new Consumer< Throwable >() {
            @Override
            public void accept( Throwable throwable ) throws Throwable {

                if ( throwable instanceof UndeliverableException ) {
                    if ( isLoggable ) {
                        Logger.e( throwable, "RxJava UndeliverableException" );
                    } else {
                        Thread thread = Thread.currentThread();
                        UncaughtExceptionHandler handler = thread.getUncaughtExceptionHandler();
                        if ( handler != null ) {
                            handler.uncaughtException( thread, throwable );
                        }
                    }
                }
            }
        } );

        //设置全局的Header构建器
        SmartRefreshLayout.setDefaultRefreshHeaderCreator( new DefaultRefreshHeaderCreator() {
            @Override
            @NonNull
            public RefreshHeader createRefreshHeader( @NonNull Context context, @NonNull RefreshLayout layout ) {

                layout.setPrimaryColors( Color.parseColor( "#00000000" ), Color.parseColor( "#666666" ) );
                return new ClassicsHeader( context );
            }
        } );
        //设置全局的Footer构建器
        SmartRefreshLayout.setDefaultRefreshFooterCreator( new DefaultRefreshFooterCreator() {
            @Override
            @NonNull
            public RefreshFooter createRefreshFooter( @NonNull Context context, @NonNull RefreshLayout layout ) {

                return new ClassicsFooter( context ).setDrawableSize( 20 );
            }
        } );
    }

    /**
     * 如果在后台时间过长,可能app会重启,再次回来会重建app,如果没有初始化第三方类库,app会崩溃
     *
     * @return true:是否需要重启App
     */
    public boolean isThirdLibInit() {

        return mInitThirdLib.get();
    }

    /**
     * @return Flowable<AppSettings>
     */
    public Flowable< AppSettings > flowAppSettings() {

        return mManager.observeProto();
    }

    /**
     * @return Observable<AppSettings>
     */
    public Observable< AppSettings > observeAppSettings() {

        return flowAppSettings().take( 1 ).toObservable();
    }

    /**
     * @param function 更新AppSettings
     */
    public void updateAppSettings( Function< AppSettings, Single< AppSettings > > function ) {

        mManager.updateData( function );
    }

    protected Context getContext() {

        return mContext;
    }

    /**
     * @return 调用该方法初始化第三方库
     */
    public Observable< ? > observeInitLibs() {

        return Observable.fromAction( new Action() {
            @Override
            public void run() throws Throwable {

                runInitLibs();
            }
        } );
    }

    /**
     * 手动初始化
     */
    public void runInitLibs() {
        /* 防止多次初始化 */
        if ( mInitThirdLib.get() ) {
            return;
        }

        /* 确保只有一个在初始化 */
        if ( mLock.tryLock() ) {

            if ( mInitThirdLib.get() ) {
                mLock.unlock();
                return;
            }

            try {
                initLibs();
            } catch ( Exception e ) {
                e.printStackTrace();
            }

            mInitThirdLib.set( true );
            mLock.unlock();
        } else {
            throw new IllegalStateException( "current init is running, please wait finish then goon" );
        }
    }

    /**
     * 子类实现初始化第三方类库
     */
    protected void initLibs() {

    }
}
